package io.jpress.core.flowable;

import com.jfinal.kit.Ret;
import io.jpress.model.FlowTemplate;
import io.jpress.web.base.AdminControllerBase;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

public class FlowableManager {

    private static final FlowableManager me = new FlowableManager();

    public static FlowableManager me() {
        return me;
    }

    /**
     * 流程类型的定义
     */
    private Map<String,FlowType> flowTypeMap = new ConcurrentHashMap<>();

    /**
     * 当用户点击【同意、拒绝、驳回】按钮时，可以通过其来提前处理一些数据
     */
    private List<UserTaskCompleteProcesser> userTaskCompleteProcessers = new CopyOnWriteArrayList<>();

    /**
     * 下线时，需要对流程进行检查，若发现某些流程正在执行时，则不允许下线
     */
    private List<UnDeployChecker> unDeployCheckers = new CopyOnWriteArrayList<>();

    public void addTaskCompleteProcesser(UserTaskCompleteProcesser builder) {
        userTaskCompleteProcessers.add(builder);
    }

    public List<UserTaskCompleteProcesser> getUserTaskCompleteProcessers() {
        return userTaskCompleteProcessers;
    }

    public void addUnDeployChecker(UnDeployChecker checker) {
        unDeployCheckers.add(checker);
    }

    public List<UnDeployChecker> getUnDeployCheckers() {
        return unDeployCheckers;
    }

    public void doCompleteProcess(Map<String, Object> variables, String taskId, String action, AdminControllerBase controller) {
        userTaskCompleteProcessers.forEach(builder -> builder.process(variables, taskId, action, controller));
    }

    public Ret doUnDeployCheck(FlowTemplate flowTemplate){
        for (UnDeployChecker unDeployChecker : unDeployCheckers) {
            Ret ret = unDeployChecker.check(flowTemplate);
            if (ret != null && ret.isFail()){
                return ret;
            }
        }
        return Ret.ok();
    }


    public void registerType(FlowType flowType){
        flowTypeMap.put(flowType.getId(), flowType);
    }

    public void removeType(String typeId){
        flowTypeMap.remove(typeId);
    }

    public FlowType getFlowType(String typeId){
        return flowTypeMap.get(typeId);
    }

    public Map<String, FlowType> getFlowTypeMap() {
        return flowTypeMap;
    }

    public void setFlowTypeMap(Map<String, FlowType> flowTypeMap) {
        this.flowTypeMap = flowTypeMap;
    }
}
